package com.example.api.service.impl;

import com.example.api.aspect.SystemLogAspect;
import com.example.api.dao.AdminDao;
import com.example.api.dao.AdminRoleDao;
import com.example.api.dao.LoginLogDao;
import com.example.api.dao.ResourceDao;
import com.example.api.dao.RoleDao;
import com.example.api.model.constants.LogisticsConstants;
import com.example.api.model.dto.LoginDto;
import com.example.api.model.entity.Admin;
import com.example.api.model.entity.AdminRole;
import com.example.api.model.entity.LoginLog;
import com.example.api.model.entity.Resource;
import com.example.api.model.entity.Role;
import com.example.api.model.support.RespBean;
import com.example.api.service.AdminService;
import com.example.api.service.EmailService;
import com.example.api.config.security.JwtTokenUtil;
import com.example.api.service.FileService;
import com.example.api.utils.SecurityUtil;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.net.InetAddress;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
public class AdminServiceImpl implements AdminService {

    @Autowired
    private AdminDao adminDao;

    @Autowired
    private AdminRoleDao adminRoleDao;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private LoginLogDao loginLogDao;

    @Autowired
    private ResourceDao resourceDao;

    @Autowired
    private EmailService emailService;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private FileService fileService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public RespBean sendEmail(String email) {
        Admin admin = adminDao.selectAdminByEmail(email);
        if (admin == null) {
            return RespBean.error("邮箱账户不存在");
        }
        emailService.sendVerificationCode(email);
        return RespBean.success("验证码发送成功");
    }

    @Override
    public RespBean selectByRoleId(Integer roleId) {
        List<Role> roles = adminRoleDao.selectByRoleId(roleId);
        if (roles.isEmpty()) {
            return RespBean.success("未初始化");
        }
        return RespBean.success("已初始化");
    }

    @Override
    public RespBean init(Admin admin) {
        if (admin.getEmail().length() < 8 || admin.getPassword().length() < 5) {
            return RespBean.error("请求参数异常");
        }
        List<Role> roles = adminRoleDao.selectByRoleId(LogisticsConstants.ROLE_ID_1);
        if (!roles.isEmpty()) {
            return RespBean.error("已存在最高权限");
        }
        admin.setCreateTime(new Date());
        admin.setEnable(LogisticsConstants.ADMIN_ENABLE_0);
        AdminRole adminRole = new AdminRole();
        adminRole.setAid(admin.getId());
        adminRole.setRid(LogisticsConstants.ROLE_ID_1);
        if (adminDao.insertSelective(admin) > 0 && adminRoleDao.insertSelective(adminRole) > 0) {
            return RespBean.success("初始化完成");
        }
        return RespBean.error("初始化失败");
    }

    @Override
    public List<Admin> findAll(String name) {
        return adminDao.findAll(SecurityUtil.getCurrentAdmin().getId(), name);
    }

    @Override
    public RespBean delete(Integer id) {
        if (adminDao.deleteByPrimaryKey(id) > 0) {
            loginLogDao.deleteByAid(id);
            return RespBean.success("删除成功");
        }
        return RespBean.error("删除失败");
    }

    @Override
    public RespBean save(Admin admin) throws Exception {
        if (StringUtils.isBlank(admin.getEmail()) && StringUtils.isBlank(admin.getUsername())) {
            return RespBean.error("请求参数异常");
        }
        Admin existAdmin = adminDao.selectAdminByEmail(admin.getEmail());
        if (Objects.nonNull(existAdmin)) {
            return RespBean.error("邮箱已存在");
        }
        admin.setPassword(passwordEncoder.encode(LogisticsConstants.DEFAULT_PASSWORD));
        admin.setCreateTime(new Date());
        admin.setEnable(LogisticsConstants.ADMIN_ENABLE_0);
        admin.setAvatar(LogisticsConstants.DEFAULT_AVATAR);
        if (adminDao.insertSelective(admin) > 0) {
            return RespBean.success("添加成功");
        }
        return RespBean.error("添加失败");
    }

    @Override
    public RespBean login(LoginDto dto) throws Exception {
        Map<String, Object> maps = Maps.newHashMap();
        Admin admin = adminDao.selectAdminByEmail(dto.getEmail());
        if (Objects.isNull(admin)) {
            return RespBean.error("用户不存在");
        }
        UserDetails userDetails = userDetailsService.loadUserByUsername(admin.getUsername());
        if (dto.getType().equals("email")) {
            Boolean result = emailService.checkVerificationCode(dto.getEmail(), dto.getCode());
            if (Boolean.FALSE.equals(result) && Objects.isNull(userDetails)) {
                return RespBean.error("邮箱或验证码错误");
            }
        }
        else {
            if (Objects.isNull(userDetails) || !passwordEncoder.matches(dto.getPassword(), userDetails.getPassword())) {
                return RespBean.error("邮箱或密码错误");
            }
        }
        if (!userDetails.isEnabled()) {
            return RespBean.error("账号被禁用");
        }
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        String token = jwtTokenUtil.createToken(userDetails, dto.isRemember() ? JwtTokenUtil.REMEMBER_EXPIRATION_TIME : JwtTokenUtil.EXPIRATION_TIME);
        maps.put("token", token);
        maps.put("tokenHead", JwtTokenUtil.TOKEN_HEAD);
        // 登录日志
        LoginLog loginLog = new LoginLog();
        loginLog.setIp(InetAddress.getLocalHost().getHostAddress());
        loginLog.setAid(admin.getId());
        loginLog.setCreateTime(new Date());
        loginLogDao.insertSelective(loginLog);
        // 记录操作用户
        SystemLogAspect.getAdmin(admin);
        return RespBean.success("登录成功", maps);
    }

    @Override
    public Admin getAdminInfo(String username) {
        Admin admin = adminDao.selectAdminByName(username);
        admin.setPassword(null);
        admin.setRoles(roleDao.selectRoleByAdmin(admin.getId()));
        return admin;
    }

    @Override
    public RespBean updatePassword(Map<String, Object> info) {
        String oldPass = (String) info.get("oldPass");
        String newPass = (String) info.get("newPass");
        Integer adminId = (Integer) info.get("adminId");
        Admin admin = adminDao.selectByPrimaryKey(adminId);
        if (passwordEncoder.matches(oldPass, admin.getPassword())) {
            admin.setPassword(passwordEncoder.encode(newPass));
            if (adminDao.updateByPrimaryKeySelective(admin) > 0) {
                return RespBean.success("更新成功");
            }
        }
        return RespBean.error("更新失败，原密码错误");
    }

    @Override
    public RespBean update(Admin admin, Authentication authentication) {
        Admin existAdmin = adminDao.selectAdminByEmail(admin.getEmail());
        if (Objects.nonNull(existAdmin)) {
            return RespBean.error("邮箱已存在");
        }
        if (adminDao.updateByPrimaryKeySelective(admin) > 0) {
            SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(admin, null, authentication.getAuthorities()));
            return RespBean.success("更新成功");
        }
        return RespBean.error("更新失败");
    }

    @Override
    public RespBean updateAdminRole(Integer aid, Integer[] rids) {
        adminRoleDao.deleteByAid(aid);
        int result = adminRoleDao.insertAdminRole(aid, rids);
        if (rids.length == result) {
            return RespBean.success("更新成功");
        }
        return RespBean.error("更新失败");
    }

    @Override
    public RespBean initPassword(Integer id) {
        Admin admin = new Admin();
        admin.setId(id);
        admin.setPassword(passwordEncoder.encode(LogisticsConstants.DEFAULT_PASSWORD));
        if (adminDao.updateByPrimaryKeySelective(admin) > 0) {
            return RespBean.success("更新成功");
        }
        return RespBean.error("更新失败");
    }

    @Override
    public RespBean updateAvatar(MultipartFile file, Integer id, Authentication authentication) throws Exception {
        Integer resourceId = fileService.upload(LogisticsConstants.UPLOAD_PREFIX_AVATAR,
                file,
                LogisticsConstants.RESOURCE_SERVICE_TYPE_1,
                LogisticsConstants.RESOURCE_OBJECT_TYPE_1);
        if (resourceId == null) {
            return RespBean.error("头像上传OSS失败");
        }
        Resource resource = resourceDao.selectByPrimaryKey(resourceId);
        if (Objects.isNull(resource)) {
            return RespBean.error("资源不存在");
        }
        Admin admin = new Admin();
        admin.setId(id);
        admin.setResourceId(resourceId);
        admin.setAvatar(resource.getOssUrl());
        if (adminDao.updateByPrimaryKeySelective(admin) > 0) {
            Admin principal = (Admin) authentication.getPrincipal();
            principal.setAvatar(resource.getOssUrl());
            SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(admin, null, authentication.getAuthorities()));
            return RespBean.success("头像更新成功", resource.getOssUrl());
        }
        return RespBean.error("头像更新失败");
    }

}